from odoo import models, _, api, fields
from odoo.exceptions import UserError
import requests
import re


class MESProductExt(models.Model):
    _inherit = 'product.template'

    s_mes_lock = fields.Boolean(string='成品、半成品、受托加工是否同步mes', default=False, copy=False)
    is_allow_to_mes = fields.Boolean(string='计划投料后运行推送mes', default=False, copy=False)

    def _cron_mes_product(self):
        """同步mes MI"""
        product_ids = self.env['product.template'].sudo().search([('s_mes_lock', '=', False),
                                                                  ('is_allow_to_mes', '=', True),
                                                                  ('categ_id.code', 'not in', ['CHP', 'BCP', 'OPFP'])])
        for product in product_ids.filtered(lambda x: not x.s_mes_lock and x.is_allow_to_mes):
            try:
                product.template_mes_upload()
            except Exception as e:
                self.env['api.records'].create({
                    'doc_type': "定时任务同步MES原材料",
                    'api_route': 'pass',
                    'api_params': f'产品：,{product.default_code}',
                    'result_json': str(e),
                    'state': 'fail'
                })

        # 可以下卡的，未同步mes的重新传
        product_ids = self.env['product.template'].sudo().search([('s_mes_lock', '=', False), ('categ_id.code', 'in', ['CHP', 'BCP', 'OPFP'])]).filtered(lambda x: x.is_allow_to_mes)
        for product in product_ids:
            try:
                product.template_mes_upload()
                product.post_mes_async()
                # 执行钻孔表推送MES
                if product.bom_ids:
                    product.bom_ids[0].upload_drill_mes({'operation_ids': []})
            except Exception as e:
                self.env['api.records'].create({
                    'doc_type': "定时任务同步mes MI及物料",
                    'api_route': 'pass',
                    'api_params': f'产品：,{product.default_code}',
                    'result_json': str(e),
                    'state': 'fail'
                })

    def send(self, url, data, token):
        headers = {
            'Content-Type': 'application/json',
            'accessToken': token,
        }
        res = requests.post(url, json=data, headers=headers)
        result = res.json()
        return result

    def post_mes_async(self, url=None):
        token = self.env['s.mes.login'].sudo().get_mes_token()
        url = self.env['s.api.config_parameter'].search([('s_key', '=', 'mes.updateImsData')]).s_value
        if not url:
            url = 'http://10.150.200.15:8888/ims-integrate/api/updateImsData'

        for product in self:
            # 计划投料后才能同步mes
            if not product.is_allow_to_mes: continue
            # 仅限成品上传git
            if product.categ_id.code and product.categ_id.code not in ['CHP', 'BCP', 'OPFP']:
                continue
            if product.sudo().bom_count != 1:
                continue
                # raise UserError(_('Only one BOM is allowed for a product'))
            crm_id = product.customer_item_code_ids
            if crm_id:
                crm_id = crm_id[0]
            # if product.categ_id.id not in  [self.env.ref('sb_sale.finished_product_type').id, self.env.ref('sb_sale.semi_product_type').id]:
            #     raise UserError(_('Only finished products can be uploaded'))
            mrp_bom = product.bom_ids
            layer_id = product.param_line_ids.filtered(lambda x: x.attribute_id.name == '层数')
            if not layer_id:
                layer_id = product.spec_line_ids.filtered(lambda x: x.attribute_id.name == '层数')
            if len(layer_id) != 1:
                raise UserError(_('Layer is required'))

            layer_infos, level_infos, seq_infos = self.get_layer_info(product)
            # 层数fold_seq等于layer_infos索引+1
            pro_seq = len(seq_infos)
            layers = [self.get_product_bom_detail(
                mrp_bom,
                is_bom_line=True,
                current_layer='0',
                next_layer='null',
                layer_qty=len(layer_infos) + 1,
                crm_id=crm_id,
                pro_seq=pro_seq
            )]
            for i, bl in enumerate(layer_infos):
                if len(bl.product_tmpl_id.name.split('-')) > 1:
                    current_layer = bl.product_tmpl_id.name.split('-')[-1]
                else:
                    current_layer = bl.product_tmpl_id.name.split('-')[0]
                # fold_seq = i+1, current_layer
                next_layer = level_infos[current_layer]
                for seq, l in enumerate(seq_infos):
                    if bl in l:
                        pro_seq = seq + 1
                        break
                layer = self.get_product_bom_detail(bl, current_layer=current_layer, next_layer=next_layer,
                                            layer_qty=i+1, crm_id=crm_id, pro_seq=pro_seq)
                layers.append(layer)

            if product.categ_id.code == 'BCP':
                mtrl_ptype = 3
            elif product.categ_id.code == 'OPFP':
                mtrl_ptype = 4
            else:
                mtrl_ptype = 2
            dtl = {
                "org_code": '0001',  # 组织代码
                "org_name": 'WTT',  # 组织名称
                "prod_code": product.default_code,  # 产品编码
                "prod_name": product.name,  # 产品名称
                "cust_prod_code": crm_id.code,  # 客户产品编码
                "cust_prod_name": product.name,  # 客户产品名称
                "cust_prod_version": crm_id.version,  # 客户产品版本
                "prod_model": crm_id.customer_item_desc,
                "mtrl_ptype": mtrl_ptype ,  # 2 成品，3半成品，4受托加工。生产阶段分类
                "remark": product.description or '',  # 备注
                "version": product.versions,  # 产品版本（SKU）
                "sku_is_valid": "Y",
                "sku_remark": "0",
                # "createdBy": mrp_bom.create_uid.name,  # 创建人
                # "createdDate": mrp_bom.create_date.strftime('%Y-%m-%d %H:%M:%S'),  # 创建时间
                "layer_info": {
                    "layer": 2 if len([l['lssuance'] == 'Y' for l in layers]) > 1 else 1,  # 层别类型
                    "fusion_state": "Y",  # 融合状态
                    "remark": "0",  # 备注
                    "layers": layers
                }
            }
            data = {
                "docType": "API_PRODUCT",
                "updateType": "UPDATE",
                'data': [dtl]
            }
            try:
                result = self.send(url, data, token)
                if result.get('resultCode') != '0000':
                    vals = {
                        'api_route': url,
                        'result_json': str(result.get('resultMsg')),
                        'api_params': data,
                        'state': 'fail',
                        'doc_type': 'API_PRODUCT'
                    }
                else:
                    product.s_mes_lock = True
                    vals = {
                        'api_route': url,
                        'api_params': data,
                        'state': 'success',
                        'doc_type': 'API_PRODUCT'
                    }

            except Exception as e:
                vals = {
                    'api_route': url,
                    'result_json': e,
                    'api_params': data,
                    'state': 'fail',
                    'doc_type': 'API_PRODUCT'
                }
            self.env['api.records'].create(vals)

    def get_layer_info(self, product_tmpl_id):
        """
        product_tmpl_id： 成品
        return:
            e.g.物料关系如下， 成品01：半成品-02/06; 半成品-02/06: 半成品-03/04, 半成品-04/05
            layer_infos: [bom_line(半成品-03/04), bom_line(半成品-04/05), bom_line(半成品-02/06)]
            level_infos: {02/06: 0, 03/04: 02/06, 04/05: 02/06},  当前层：下一层
            seq_infos: [[半成品-03/04, 半成品-04/05], [半成品-02/06], [成品01]],  加工顺序
        """
        layer_infos = []
        level_infos = {}
        seq_infos = [[product_tmpl_id]]
        visited_01 = [product_tmpl_id]
        p = visited_01.pop(0)
        while p:
            mrp_bom = p.bom_ids
            bom_lines = mrp_bom.bom_line_ids.filtered(lambda x: x.product_tmpl_id.bom_count)
            sub_layer_infos = []
            for bl in bom_lines:
                if len(bl.product_tmpl_id.name.split('-')) > 1:
                    # e.g. 半成品
                    current_level = bl.product_tmpl_id.name.split('-')[-1]
                else:
                    current_level = bl.product_tmpl_id.name.split('-')[0]
                if bl.parent_product_tmpl_id and len(bl.parent_product_tmpl_id.name.split('-')) > 1:
                    # e.g. 成品层
                    next_level = bl.parent_product_tmpl_id.name.split('-')[-1]
                else:
                    next_level = "0"
                level_infos[current_level] = next_level
                sub_layer_infos.append(bl)
                # layer_infos.insert(0, bl.product_tmpl_id.name)
                visited_01.append(bl.product_tmpl_id)
            layer_infos = sub_layer_infos + layer_infos
            if sub_layer_infos:
                seq_infos.insert(0, sub_layer_infos)
            if visited_01:
                p = visited_01.pop(0)
            else:
                p = False
        return layer_infos, level_infos, seq_infos

    def get_unit_number(self, product_id):
        uom_panel_width = self.env.ref('pcbmanufact.uom_panel_width')
        uom_panel_length = self.env.ref('pcbmanufact.uom_panel_length')
        uom_set_width = self.env.ref('pcbmanufact.uom_set_width')
        uom_set_length = self.env.ref('pcbmanufact.uom_set_length')
        uom_pcs_width = self.env.ref('pcbmanufact.uom_pcs_width')
        uom_pcs_length = self.env.ref('pcbmanufact.uom_pcs_length')
        PCS = self.env.ref('pcbmanufact.uom_part')
        PANEL = self.env.ref('pcbmanufact.uom_panel')
        SET = self.env.ref('pcbmanufact.uom_set')
        uom_ids = product_id.uom_value_ids.mapped('uom_id')
        pnl_width = 0
        pnl_length = 0
        if uom_panel_width in uom_ids and uom_panel_length in uom_ids:
            pnl_width = product_id.uom_value_ids.filtered(lambda x: x.uom_id.id == uom_panel_width.id).uom_value
            pnl_length = product_id.uom_value_ids.filtered(lambda x: x.uom_id.id == uom_panel_length.id).uom_value
        set_width = 0
        set_length = 0
        if uom_set_width in uom_ids and uom_set_length in uom_ids:
            set_width = product_id.uom_value_ids.filtered(lambda x: x.uom_id.id == uom_set_width.id).uom_value
            set_length = product_id.uom_value_ids.filtered(lambda x: x.uom_id.id == uom_set_length.id).uom_value
        pcs_width = 0
        pcs_length = 0
        if uom_pcs_width in uom_ids and uom_pcs_length in uom_ids:
            pcs_width = product_id.uom_value_ids.filtered(lambda x: x.uom_id.id == uom_pcs_width.id).uom_value
            pcs_length = product_id.uom_value_ids.filtered(lambda x: x.uom_id.id == uom_pcs_length.id).uom_value

        pcs_qty = 1
        if PCS in uom_ids:
            pcs_qty = product_id.uom_value_ids.filtered(lambda x: x.uom_id.id == PCS.id).uom_value
        panel_qty = 1
        if PANEL in uom_ids:
            pcs_qty = product_id.uom_value_ids.filtered(lambda x: x.uom_id.id == PANEL.id).uom_value
        set_qty = 1
        if SET in uom_ids:
            set_qty = product_id.uom_value_ids.filtered(lambda x: x.uom_id.id == SET.id).uom_value
        return [pnl_width, pnl_length, set_width, set_length, pcs_width, pcs_length, panel_qty, set_qty, pcs_qty]

    def get_product_bom_detail(self, bom, is_bom_line=False, current_layer='', next_layer='', layer_qty=0, crm_id=None, pro_seq=1):
        if is_bom_line:
            product_template_id = bom.product_tmpl_id
        else:
            product_template_id = bom.product_tmpl_id
            if product_template_id.bom_count != 1:
                raise UserError(_('Only one BOM is allowed for a product'))
            bom = product_template_id.bom_ids
        if not bom:
            return {}
        # 下方信息需要维护销售 报价单
        if not crm_id:
            crm_id = product_template_id.customer_item_code_ids
        if not crm_id:
            raise UserError(_('Customer item code is required'))
        crm_id = crm_id[0]
        s_size = self.get_unit_number(product_template_id)
        bom_list = self.get_bom_list(bom)  # BOM明细
        eng_params = self.get_eng_params(bom)  # 工程参数
        prod_params = self.get_prod_params(product_template_id)  # 产品参数
        wp_params = self.get_wp_params(bom)  # 工序参数
        mtools = self.get_mtools()  # 模治具
        tps = self.get_tps(bom)  # 工艺路线
        drill_bits = self.get_drill_bits()  # 钻针
        router_bits = self.get_router_bits()  # 锣刀
        value_pnl = product_template_id.value_pnl
        value_set = product_template_id.value_set
        param_line_ids = product_template_id.param_line_ids
        cust_surface_handle  = param_line_ids.filtered(lambda x: x.attribute_id.name == '表面处理').z_eng_name if param_line_ids else ''
        cust_surface_handle_cn  = param_line_ids.with_context(lang='zh_CN').filtered(lambda x: x.attribute_id.name == '表面处理').value_id.name if param_line_ids else ''
        try:
            thick  = float(param_line_ids.with_context(lang='zh_CN').filtered(lambda x: x.attribute_id.name == '成品板厚').value_id.name if param_line_ids else 0)
        except Exception as e:
            thick = 0
        mi_info = {
            "layer_qty": layer_qty,  # 层数
            "thick": thick,  # 产品厚度  成品板厚
            "cust_surface_handle": cust_surface_handle,
            "cust_surface_handle_cn：": cust_surface_handle_cn,
            "cust_code": crm_id.customer_id.code,  # 客户编号 crm_id.partner_id.display_name
            "x_out": 0,  # 叉板比例≤（%）
            "stay_qty": 0,  # 预留比例（%）
            "plate_length": 0,  # 基材长度（mm）
            "plate_width": 0,  # 基材宽度（mm）
            "plate_thick": 0,  # 基材厚度（mm）
            "pnl_length": s_size[1],  # PNL长度（mm）
            "pnl_width": s_size[0],  # PNL宽度（mm）
            "pnl_mm": (s_size[1] * s_size[0]) / 1000000,  # PNL面积（m²）
            "set_length": s_size[3],  # SET长度（mm）
            "set_width": s_size[2],  # SET宽度（mm）
            "set_mm": (s_size[2] * s_size[3]) / 1000000,  # SET面积（m²）
            "pcs_length": s_size[5],  # PCS长度（mm）
            "pcs_width": s_size[4],  # PCS宽度（mm）
            "pcs_mm": (s_size[5] * s_size[4]) / 1000000,  # PCS面积（m²）
            "pnl_pcs_qty": value_pnl,  # 1PNL = ?PCS
            "set_pcs_qty": value_set,  # 1SET = ?PCSpanel_qty, set_qty, pcs_qty
            "pnl_set_qty": value_pnl / value_set,  # 1PNL = ?SET
            "pnl_qty": 72,  # PNL数量
            "remain_qty": 36,  # PNL余数
            "plate_weight": 0,  # 基板铜厚（μm）
            "press_program": "1",  # 压合程序
            "pass_qty": 0,  # 良率比例（%）
            "pass_type": 1,  # 良率类型
            "board_type": 1,  # 产品类型
            "is_mapping": "N",  # Defect-Mapping
            "emergency_type": 0,  # 紧急状态
            "remark": "0",  # 备注
            # "plateQty": 0,  # 电镀均匀性
            # "platQty": 0,  # 电镀面积
            # "deepQty": 0,  # 电镀铜厚
            # "holeQty": 0,  # 对准度
            # "holdStat": 0,  # HOLD状态
            "fold_qty": 0,  # 叠板数量
            "is_valid": "Y",
            "eng_params": eng_params,
            "prod_params": prod_params,
            "wp_params": wp_params,
            "mtools": mtools,
            "tp": tps,
            "drill_bits": drill_bits,
            'router_bits': router_bits
        }
        # 层别列表
        layers = {
            "current_layer": current_layer,  # 当前层
            "next_layer": next_layer,  # 下一层
            "lssuance": 'N' if bom.bom_line_ids.filtered(lambda x: x.product_tmpl_id.bom_count > 0) else 'Y',  # 是否发料层  外层是,内层否
            "processing_sequence": pro_seq,  # 加工顺序  sequence
            "layer_type": current_layer,  # 层别  当前层
            "fold_seq": layer_qty,  # 层数
            "remark": "",  # 备注
            "mi_info": mi_info,
            "bom_list": bom_list
        }
        return layers

    @classmethod
    def get_bom_list(cls, bom):
        product_id = bom.product_tmpl_id
        bom_list = [
            #     {
            #     "seq": 0,  # 序号
            #     "mtrl_code": product_id.default_code,  # 物料编码
            #     "is_main": "N",  # 是否主料
            #     "main_code": product_id.default_code,  # 主料编码
            #     "dosage": bom.product_qty,  # 用量
            #     # "point_str": "",  # 点位
            #     "remark": product_id.description or '',  # 备注
            #     "wp_code": 'OLC01',  # 工序代码
            #     # "wpName": "",  # 工序名称
            #     "unit": bom.product_uom_id.name,  # 单位
            #     "standard": 0,  # 标准消耗
            #     "is_component": "Y"  # 是否为部件
            # }
        ]
        for index, line_record in enumerate(bom.bom_line_ids):
            line_product = line_record.product_id
            if line_product.detailed_type != 'product':
                continue
            bom_list.append({
                "seq": index + 1,  # 序号
                "mtrl_code": line_product.default_code,  # 物料编码
                "is_main": "Y",  # 是否主料
                "main_code": line_product.default_code,  # 主料编码
                "dosage": line_record.product_qty,  # 用量
                # "point_str": "",  # 点位
                "remark": line_product.description or '',  # 备注
                "wp_code": line_record.s_operation_id.code if line_record.s_operation_id  else 'OLC01' ,  # 工序代码
                # "wpName": "",  # 工序名称
                "unit": line_record.product_uom_id.name,  # 单位
                "standard": 0,  # 标准消耗
                "is_component": "Y"  # 是否为部件
            })
        return bom_list

    @classmethod
    def get_eng_params(cls, bom):
        """工程参数"""
        bom = bom.with_context(lang='zh_CN')
        attribute_list = ['内控面铜', '内控孔铜', '字符油墨型号', '字符颜色', '周期格式', '孔内锡厚', '客规Au厚', '客规Ni厚', '周期面次', '锡厚', '内控Au厚']
        eng_param = []
        for param in bom.operation_ids:
            workercenter_id = param.workcenter_id
            for pa in param.param_line_ids:
                if not pa.attribute_id.code:
                    continue
                # if pa.attribute_id.code == 'CUT01_00':
                #     print('------')

                exists = any(item['param_code'] == pa.attribute_id.code for item in eng_param)
                if exists:
                    continue
                eng_param.append({
                    "wp_code": workercenter_id.code,  # 工序编码
                    "wp_name": workercenter_id.name,  # 工序名称
                    "param_code": pa.attribute_id.code,  # 参数编码
                    "param_name": pa.attribute_id.name,  # 参数名称
                    # "param_type": 1,  # 参数类型
                    # "param_stat": 1,  # 参数属性
                    "param_value": '0000',  # 参数值
                    "param_desc": "",  # 参数描述
                    # "top_value": "0",  # 参数上限
                    # "down_value": "0",  # 参数下限
                    # "unit": "0",  # 参数单位
                    "is_code": "Y",  # 一维码
                    "is_valid": "Y",  # 启用状态
                    "remark": pa.value_id.name  # 备注
                })
        for pl in bom.product_tmpl_id.param_line_ids:
            if pl.attribute_id.name in attribute_list:
                eng_param.append({
                    "wp_code": '',  # 工序编码
                    "wp_name": '',  # 工序名称
                    "param_code": pl.attribute_id.code,  # 参数编码
                    "param_name": pl.attribute_id.name,  # 参数名称
                    # "param_type": 1,  # 参数类型
                    # "param_stat": 1,  # 参数属性
                    "param_value": '0000',  # 参数值
                    "param_desc": "",  # 参数描述
                    # "top_value": "0",  # 参数上限
                    # "down_value": "0",  # 参数下限
                    # "unit": "0",  # 参数单位
                    "is_code": "Y",  # 一维码
                    "is_valid": "Y",  # 启用状态
                    "remark": pl.value_id.name  # 备注
                })

        return eng_param

    @classmethod
    def get_prod_params(cls, product):
        """产品参数"""
        prod_param = []
        for pp in product.param_line_ids:
            if not pp.attribute_id.code:
                continue
            prod_param.append({
                "param_code": pp.attribute_id.code,  # 参数编码
                "param_name": pp.attribute_id.name,  # 参数名称
                "param_type": 1,  # 参数类型
                "param_value": pp.value_id.name,  # 参数值
                "param_desc": "",  # 参数描述
                # "top_value": "0",  # 参数上限
                # "down_value": "0",  # 参数下限
                # "unit": "0",  # 参数单位
                "is_code": "Y",
                "is_valid": "Y",
                "remark": "",  # 备注
                # "hole_qty": 0  # 钻孔对准度
            })
        for sa in product.spec_line_ids:
            if not sa.attribute_id.code:
                continue
            prod_param.append({
                "param_code": sa.attribute_id.code,  # 参数编码
                "param_name": sa.attribute_id.name,  # 参数名称
                "param_type": 1,  # 参数类型
                "param_value": sa.value_id.name,  # 参数值
                "param_desc": "",  # 参数描述
                # "top_value": "0",  # 参数上限
                # "down_value": "0",  # 参数下限
                # "unit": "0",  # 参数单位
                "is_code": "Y",
                "is_valid": "Y",
                "remark": "",  # 备注
                # "hole_qty": 0  # 钻孔对准度
            })
        return prod_param

    @classmethod
    def get_wp_params(cls, bom):
        """工序参数"""
        wp_params = []
        for record in bom.operation_ids:
            wp_params.append({  # 工序参数
                "wp_code": record.workcenter_id.code,
                "wp_name": record.workcenter_id.name,
                "norm_date": 1,
                "is_move": "N",
                "is_out": "N",
                "is_mix": "N",
                "is_valid": "Y",
                "change_stat": "N",
                "show_stat": "N" ,
                "top_stat": "Y" if record.workcenter_id.is_enter_bcode else 'N',
                "down_stat": "Y" if record.workcenter_id.is_enter_bcode else 'N',
                "is_notify": "Y" if record.workcenter_id.is_enter_bcode else 'N',
                "notify_point": 1,
                "remark": ""
            })
        return wp_params

    @classmethod
    def get_mtools(cls):
        """模治具"""
        dtl = {  # 模治具
            "mtool_code": "twy-test-001",
            "mtool_name": "测试模治具001",
            "loc_stat": 1,
            "mtool_stat": 0,
            "tot_used_times": 1,
            "mf_dev_sn": "string",
            "sup_id": "string",
            "mf_id": "string",
            "asset_code": "string",
            "store_code": "liyao_zzck",
            "storeloc_code": "cscw",
            "scrap_time": "string",
            "pd_date": "string",
            "pr_date": "string",
            "last_uk_date": "string",
            "wp_code": "liyao_ceshi12",
            "pl_code": "string",
            "dev_code": "string",
            "pr_id": "string",
            "in_date": "string",
            "mdt_pas_stat": 0,
            "mtool_md": {
                "mmd_code": "twy-test-mmd-001",
                "mmd_name": "测试模治具型号001",
                "scrap_warn_times": 1,
                "scrap_warn_days": 1,
                "is_valid": "Y",
                "min_sk_qty": 0,
                "max_sk_qty": 0,
                "price": 0,
                "munit": "string",
                "purchase_url": "string",
                "store_code": "string",
                "storeloc_code": "string",
                "remark": "测试模治具型号001备注"
            },
            "remark": "测试模治具001备注"
        }
        return []

    @classmethod
    def get_tps(cls, bom):
        """工艺路线"""
        wp_node_list = []
        index = 1
        for record in bom.operation_ids:
            wp_node_list.append({
                "seq": index,
                "wp_code": record.workcenter_id.code,
                "remark": ""
            })
            index += 1
        tps = {
            "tp_code": bom.product_tmpl_id.name,
            "tp_name": bom.product_tmpl_id.name,
            "is_valid": "Y",
            "wp_node_list": wp_node_list
        }
        return tps

    @classmethod
    def get_drill_bits(cls):
        """钻针"""
        dtl = {
            "mtool_code": "twy-test-002",
            "mtool_name": "测试模治具002-钻针",
            "loc_stat": 1,
            "mtool_stat": 0,
            "tot_used_times": 1,
            "cur_abr_times": 1,
            "actual_qty": 1,
            # "mf_dev_sn": "string",
            # "sup_id": "string",
            # "mf_id": "string",
            # "asset_code": "string",
            "store_code": "liyao_zzck",
            "storeloc_code": "cscw",
            # "scrap_time": "string",
            # "pd_date": "string",
            # "pr_date": "string",
            # "last_uk_date": "string",
            # "wp_code": "string",
            # "pl_code": "string",
            # "dev_code": "string",
            # "pr_id": "string",
            # "in_date": "string",
            "mdt_pas_stat": 0,
            "mmd_type": {
                "mmd_code": "twy-test-mmd-002",
                "mmd_name": "测试模治具型号002-钻针",
                "default_qty": 1,
                "is_valid": "Y",
                "drill_type": "",
                "drill_qty": 1,
                "polish_qty": 1,
                "norm_qty": 1,
                "span_qty": 1,
                "scrap_qty": 1,
                "diameter": 1,
                "min_sk_qty": 1,
                "max_sk_qty": 100,
                "price": 1,
                "munit": "",
                "purchase_url": "",
                "store_code": "liyao_zzck",
                "storeloc_code": "cscw",
                "remark": "测试模治具型号002-钻针备注"
            },
            "remark": "测试模治具002-钻针备注"
        }
        return []

    @classmethod
    def get_router_bits(cls):
        """锣刀"""
        dtl = {
            "mtool_code": "twy-test-003",
            "mtool_name": "测试模治具003-锣刀",
            "loc_stat": 1,
            "mtool_stat": 0,
            "tot_used_times": 1,
            # "cur_abr_times": 0,
            "actual_qty": 1,
            # "mf_dev_sn": "string",
            # "sup_id": "string",
            # "mf_id": "string",
            # "asset_code": "string",
            "store_code": "liyao_zzck",
            "storeloc_code": "cscw",
            # "scrap_time": "string",
            # "pd_date": "string",
            # "pr_date": "string",
            # "last_uk_date": "string",
            # "wp_code": "string",
            # "pl_code": "string",
            # "dev_code": "string",
            # "pr_id": "string",
            # "in_date": "string",
            "mdt_pas_stat": 0,
            "mmd_type": {
                "mmd_code": "twy-test-mmd-003",
                "mmd_name": "测试模治具型号003锣刀",
                "default_qty": 1,
                "is_valid": "Y",
                # "code_content": "string",
                # "spec": "string",
                "scrap_qty": 1,
                # "cut_type": "string",
                # "cut_length": 0,
                "diameter": 1,
                # "min_sk_qty": 0,
                # "max_sk_qty": 0,
                # "price": 0,
                # "munit": "string",
                # "purchase_url": "string",
                # "store_code": "string",
                # "storeloc_code": "string",
                "remark": "测试模治具型号003-锣刀备注"
            },
            "remark": "测试模治具003-锣刀备注"
        }
        return []

    # 物料信息
    def template_mes_upload(self):
        template_list = []
        for record in self:
            name = record.name
            mtrl_spcl = 1
            # 物料信息PP属性 如果是PP材料mtrl_spcl值为6
            bs_mtrl_pp_pcb = []
            try:
                if "PP" in name:
                    mtrl_spcl = 6
                    end = name.split(' ')[-1]
                    if '*' in end:
                        end = end.split('*')
                    else:
                        end = end.split('x')
                    bs_mtrl_pp_pcb.append({
                        "pp_length": int(re.findall(r'\d+', end[0])[0]) if len(end) >= 1 else 0,  # PP长度
                        "pp_width": int(re.findall(r'\d+', end[1])[0]) if len(end) >= 2 else 0,  # PP宽度
                        "pp_thick": int(re.findall(r'\d+', end[2])[0]) if len(end) >= 3 else 0,  # PP厚度
                        "loss": 0,  # 损耗
                        "pp_unit": 0  # PP单位 1：片 2：卷
                    })
            except Exception as e:
                mtrl_spcl = 1
            # 物料信息 铜箔属性 如果是铜箔材料mtrl_spcl值为7
            bs_mtrl_copper_pcb = []
            try:
                if '铜箔' in name:
                    mtrl_spcl = 7
                    end = name.split('_')[-1]
                    if 'HTE' in end:
                        end = end.split('HTE')
                    else:
                        end = end.split('RTF')
                    bs_mtrl_copper_pcb.append({
                        "loss": 0,  # 损耗
                        "copper_width": 0,  # 铜箔宽度
                        "copper_thick": int(re.findall(r'\d+', end[0])[0]) if len(end) >= 1 else 0,  # 铜箔厚度
                        "copper_length": int(re.findall(r'\d+', end[1])[0]) if len(end) >= 2 else 0  # 铜箔长度
                    })
            except Exception as e:
                mtrl_spcl = 1
            # 物料油墨属性 如果是油墨材料mtrl_spcl值为8
            bs_mtrl_ink_pcb = [
                # {
                #     "ink_colour": "string",#颜色
                #     "wait_date": 0,#静置时间(小时)
                #     "open_date": 0,#保质期(小时)
                #     "down_value": 0,#粘度下限
                #     "top_value": 0,#粘度上限
                #     "dark_type": "string"#油墨环节 数字英文逗号隔开如2,3,4,5;  2：启罐 3：搅拌 4：静置 5：启用
                # }
            ]
            # 物料信息板材属性 如果是板材材料mtrl_spcl值为9
            bs_mtrl_board_pcb = [
                # {
                #     "board_copper": 0,#基材铜厚（μm）
                #     "board_thick": 0,#基材厚度（mm）
                #     "pnl_length": 0,#基材长度（mm）
                #     "pnl_width": 0#基材宽度（mm）
                # }
            ]
            # 物料干膜制冷属性 如果是干膜材料mtrl_spcl值为12
            bs_mtrl_film = []
            try:
                if '干膜' in name:
                    mtrl_spcl = 12
                    end = name.split('-')[-1]
                    if '_' in end:
                        end = end.split('_')
                    new_end = end[-1].split('x')
                    bs_mtrl_film.append({
                        "thaw_qty": 0,  # 回冰次数 输入0以及正整数
                        "thaw_date": 0,  # 解冻时间(小时)
                        "film_thick": int(re.findall(r'\d+', end[1])[0]) if len(end) >= 2 else 0,  # 干膜厚度（mm）
                        "film_length": int(re.findall(r'\d+', new_end[1])[0]) if len(new_end) >= 2 else 0,  # 干膜长度（mm）
                        "film_width": int(re.findall(r'\d+', new_end[0])[0]) if len(new_end) >= 1 else 0,  # 干膜宽度（mm）
                        "film_loss": 0,  # 干膜损耗
                        "film_type": "string"  # 干膜环节 数字英文逗号隔开如2,3;  2：解冻 3：启用
                    })
            except Exception as e:
                mtrl_spcl = 1
            # 物料树脂属性
            bs_mtrl_sr = [
                # {
                #     "temp_dpart": 0,#回温时间（小时）
                #     "cool_dpart": 0,#最小冷冻时间（分钟）
                #     "temp_times": 0#最大回温次数
                # }
            ]
            # 物料垫板属性
            pcb_mtrl_plate = []
            try:
                if '垫板' in name:
                    end = name.split('_')[-1]
                    if 'x' in end:
                        end = end.split('x')
                    else:
                        end = end.split('*')
                    pcb_mtrl_plate.append({
                        "plate_length": int(re.findall(r'\d+', end[1])[0]) if len(end) >= 2 else 0,  # 垫板长度
                        "plate_width": int(re.findall(r'\d+', end[0])[0]) if len(end) >= 1 else 0,  # 垫板宽度
                    })
            except Exception as e:
                mtrl_spcl = 1
            # 物料铝片属性
            pcb_mtrl_flake = []
            try:
                if '铝片' in name:
                    end = name.split('_')[-1]
                    if 'x' in end:
                        end = end.split('x')
                    else:
                        end = end.split('*')
                    pcb_mtrl_flake.append({
                        "flake_length": int(re.findall(r'\d+', end[1])[0]) if len(end) >= 2 else 0,  # 铝片长度
                        "flake_width": int(re.findall(r'\d+', end[0])[0]) if len(end) >= 1 else 0  # 铝片宽度
                    })
            except Exception as e:
                mtrl_spcl = 1
            # 存储位置
            bs_storeloc_mtrl = [
                # {
                #     "store_code": "string",#仓库编码
                #     "storeloc_code": "string",#储位编码
                #     "storeloc_class": 3#指定类型 1：指定 2：指定+默认 3：默认
                # }
            ]
            # 除了成品和半成品, 其他全是原材料
            smi = self.env.ref('sb_sale.semi_product_type')  # 半成品
            finis = self.env.ref('sb_sale.finished_product_type')  # 成品
            template_list.append({
                "org_id": "0001",
                "mtrl_code": record.default_code,  # 物料编码
                "mtrl_name": record.name,  # 物料名称
                "mtrl_desc": record.standards or '',  # 物料规格
                "erp_mtrl_id": record.default_code,  # ERP物料编码
                "mtype_code": record.categ_id.code,  # 物料类别代码
                # 1：普通物料 4：PCB 5：辅料 6：PP 7：铜箔 8：油墨 9：板材 10：药水 11：树脂 12：干膜 13：铜球 14：金粉 15：铜粉 16：金盐 17：垫板 18：铝片
                "mtrl_spcl": mtrl_spcl,  # 特殊分类
                "mtrl_ptype": 0 if record.categ_id.id in [smi.id, finis.id] else 1,  # 生产阶段 0:未分类 1:原材料
                "pack_qty": 0,  # 最小包装数
                "min_sk_qty": 0,  # 最低安全库存
                "max_sk_qty": 0,  # 最高安全库存
                "mg_type": 1,  # 管理方式 1：LPN管理
                "munit": record.uom_id.name,  # 单位
                "cost_class": 1 if record.categ_id.id in [smi.id, finis.id] else 0,  # 成本分类 0：原料 1：物料 3：消耗品
                "is_place": "Y",  # 扣数状态 N:未启用 Y:已启用
                "is_valid": "Y",  # 启用状态 N:未启用 Y:已启用
                "remark": "",  # 备注
                "bs_mtrl_pp_pcb": bs_mtrl_pp_pcb,  # 物料信息PP属性
                "bs_mtrl_copper_pcb": bs_mtrl_copper_pcb,  # 物料信息 铜箔属性
                "bs_mtrl_ink_pcb": bs_mtrl_ink_pcb,  # 物料油墨属性
                "bs_mtrl_board_pcb": bs_mtrl_board_pcb,  # 物料信息板材属性
                "bs_mtrl_film": bs_mtrl_film,  # 物料干膜制冷属性
                "bs_mtrl_sr": bs_mtrl_sr,  # 物料树脂属性
                "pcb_mtrl_plate": pcb_mtrl_plate,  # 物料垫板属性
                "pcb_mtrl_flake": pcb_mtrl_flake,  # 物料铝片属性
                "bs_storeloc_mtrl": bs_storeloc_mtrl  # 存储位置
            })
        data = {
            "docType": "BS_MTRL",
            "updateType": "UPDATE",
            "data": template_list
        }
        self.env['s.mes.upload'].upload_data(data)
